package com.program.facesigninsystem.controller;

import cn.yueshutong.springbootstartercurrentlimiting.annotation.CurrentLimiter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.program.facesigninsystem.entity.ResponseModel;
import com.program.facesigninsystem.entity.SignInActivity;
import com.program.facesigninsystem.entity.SignInCourse;
import com.program.facesigninsystem.entity.SignInLink;
import com.program.facesigninsystem.iteration.dto.NoSignInParam;
import com.program.facesigninsystem.iteration.entity.SigninactivityEntity;
import com.program.facesigninsystem.iteration.entity.SigninclassEntity;
import com.program.facesigninsystem.iteration.entity.SigninlinkEntity;
import com.program.facesigninsystem.iteration.mapper.SigninactivityMapper;
import com.program.facesigninsystem.iteration.mapper.SigninclassMapper;
import com.program.facesigninsystem.service.ISignInActivityService;
import com.program.facesigninsystem.service.ISignInCourseService;
import com.program.facesigninsystem.service.ISignInRecordService;
import com.program.facesigninsystem.service.SignInClassService;
import com.program.facesigninsystem.service.impl.SignInActivityService;
import com.program.facesigninsystem.util.ChangeDate;
import com.program.facesigninsystem.util.PageUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;


@CrossOrigin
@RestController
@RequestMapping(value = "/cou")
public class SignInCourseController {
    private static Logger log = Logger.getLogger(SignInActivityController.class.toString());
    private static final int LOCATION = 522;
    private static final int CODE = 829;

    @Resource
    ISignInCourseService iSignInCourseService;
    @Resource
    ISignInActivityService iSignInActivityService;
    @Resource
    ISignInRecordService iSignInRecordService;
    @Resource
    SignInClassService signInClassService;
    @Resource
    SigninclassMapper signinclassMapper;
    @Resource
    SigninactivityMapper signinactivityMapper;
    @Autowired
    private SignInActivityService signInActivityService;

    @RequestMapping(value = "/findCouByuid",method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public  void findCouByuid(
            HttpServletResponse resp,
            @RequestParam("uid")String uid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ){
        List<SignInCourse> SignInCourseList= iSignInCourseService.selectbyuid(uid,pageNum,pageSize);
        List<JSONObject> data = new ArrayList<>();
        try{
            for(SignInCourse signInCourse:SignInCourseList){
                JSONObject courseObject = new JSONObject();
                courseObject.put("ccid",signInCourse.getCcid());
                courseObject.put("name",signInCourse.getName());
                courseObject.put("week",signInCourse.getWeek());
                courseObject.put("section",signInCourse.getSection());
                courseObject.put("year",signInCourse.getYear());
                courseObject.put("Semester",signInCourse.getSemester());
                courseObject.put("uid",signInCourse.getUid());
                courseObject.put("createtime",signInCourse.getCreatetime());
                courseObject.put("signinclassid",signInCourse.getSigninclass_id());
                courseObject.put("cid", signInCourse.getCid());


                data.add(courseObject);
            }
            JSONObject data1 = PageUtil.wrap(data,"data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data1.toString());
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }
    @RequestMapping(value = "/findActByccid",method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public  void findActByccid(
            HttpServletResponse resp,
            @RequestParam("ccid")String ccid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ){
        List<SignInActivity> SignInActivityList=iSignInCourseService.selectActbyccid(ccid,pageNum,pageSize);
        List<JSONObject> data = new ArrayList<>();
        try{
            for (SignInActivity anActivityList : SignInActivityList) {
                JSONObject act = JSONObject.fromObject(anActivityList);
//                String cid = act.getString("cid");
//                if ((cid != null) && (!"".equals(cid))) {
//                    Classes classes = iClassesService.selectClass(cid);
//                    if (classes != null) {
//                        act.accumulate("className", classes.getName());
//                    } else {
//                        act.accumulate("className", "");
//                    }
//                }
                String cid = act.getString("cid");
                if ((cid != null) && (!"".equals(cid))) {
                    SigninclassEntity signinclassEntity = signinclassMapper.selectById(Integer.parseInt(cid));
                    if (signinclassEntity != null) {
                        act.accumulate("className", signinclassEntity.getName());
                    } else {
                        act.accumulate("className", "");
                    }
                }
                act.remove("tid");
                Object[] linkList = iSignInActivityService.selectLinkByActId(act.getString("actId"));
                List<JSONObject> temp = new ArrayList<>();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String currentTime = dateFormat.format(System.currentTimeMillis());
                for (Object aLinkList : linkList) {
                    JSONObject link = JSONObject.fromObject(aLinkList);
                    link.remove("actId");
                    if (link.getString("endTime") != null && !link.getString("endTime").equals("") &&currentTime.compareTo(link.getString("endTime")) > 0 && (!link.getString("endTime").equals(link.getString("startTime")))) {
                        link.put("status", 2);
                    }
                    temp.add(link);
                }
                act.accumulate("links", temp);
                data.add(act);
            }
            JSONObject data1 = PageUtil.wrap(data,"data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data1.toString());
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }

    @RequestMapping(value = "/findActByccid1",method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public  void findActByccid1(
            HttpServletResponse resp,
            @RequestParam("ccid")String ccid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10000") int pageSize
    ){
        List<SignInActivity> SignInActivityList=iSignInCourseService.selectActbyccid(ccid,pageNum,pageSize);
        List<JSONObject> data = new ArrayList<>();
        try{
            for (SignInActivity anActivityList : SignInActivityList) {
                JSONObject act = JSONObject.fromObject(anActivityList);
//                String cid = act.getString("cid");
//                if ((cid != null) && (!"".equals(cid))) {
//                    Classes classes = iClassesService.selectClass(cid);
//                    if (classes != null) {
//                        act.accumulate("className", classes.getName());
//                    } else {
//                        act.accumulate("className", "");
//                    }
//                }
                String cid = act.getString("cid");
                if ((cid != null) && (!"".equals(cid))) {
                    SigninclassEntity signinclassEntity = signinclassMapper.selectById(Integer.parseInt(cid));
                    if (signinclassEntity != null) {
                        act.accumulate("className", signinclassEntity.getName());
                    } else {
                        act.accumulate("className", "");
                    }
                }
                act.remove("tid");
                Object[] linkList = iSignInActivityService.selectLinkByActId(act.getString("actId"));
                List<JSONObject> temp = new ArrayList<>();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String currentTime = dateFormat.format(System.currentTimeMillis());
                for (Object aLinkList : linkList) {
                    JSONObject link = JSONObject.fromObject(aLinkList);
                    link.remove("actId");
                    if (link.getString("endTime") != null && !link.getString("endTime").equals("") &&currentTime.compareTo(link.getString("endTime")) > 0 && (!link.getString("endTime").equals(link.getString("startTime")))) {
                        link.put("status", 2);
                    }
                    temp.add(link);
                }
                act.accumulate("links", temp);
                data.add(act);
            }
            JSONObject data1 = PageUtil.wrap(data,"data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data.toString());
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }
    @ApiOperation("删除课程")
    @RequestMapping(value = "/deletecou",method = RequestMethod.POST)
    public ResponseModel deletecou(@RequestParam(value = "ccid",required = false) String ccid) {
        if (iSignInCourseService.deleteCourse(ccid))
            return new ResponseModel(200, "删除课程成功");
        else
            return new ResponseModel(500, "删除课程失败");
    }
    @ApiOperation("申请加入组织")
    @RequestMapping(value = "/couapplygroup",method = RequestMethod.POST)
    public ResponseModel couapplygroup(@RequestParam String oid, @RequestParam String ccid) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = dateFormat.format(System.currentTimeMillis());
        if (iSignInCourseService.applygroup(oid, ccid,currentTime))
            return new ResponseModel(200, "申请成功");
        else
            return new ResponseModel(500, "申请失败,在申请中或者已经加入该组织");
    }
    @ApiOperation("驳回申请")
    @RequestMapping(value = "/courejectapply",method = RequestMethod.POST)
    public ResponseModel courejectapply(@RequestParam String coid) {
        if (iSignInCourseService.rejectapply(coid))
            return new ResponseModel(200, "拒绝加入成功");
        else
            return new ResponseModel(500, "拒绝失败");
    }
    @ApiOperation("通过申请")
    @RequestMapping(value = "/coupassapply",method = RequestMethod.POST)
    public ResponseModel coupassapply(@RequestParam String coid) {
        if (iSignInCourseService.passapply(coid))
            return new ResponseModel(200, "批准申请成功");
        else
            return new ResponseModel(500, "批准申请失败");
    }
    @ApiOperation("解除绑定")
    @RequestMapping(value = "/couuntiebind",method = RequestMethod.POST)
    public ResponseModel couuntiebind(@RequestParam String coid) {
        if (iSignInCourseService.untiebind(coid))
            return new ResponseModel(200, "解除绑定成功");
        else
            return new ResponseModel(500, "解除绑定失败");
    }
    @ApiOperation("查看课程申请记录")
    @RequestMapping(value = "/couapplyhistory",method = RequestMethod.GET)
    public void couselectapplyhistory(
            HttpServletResponse resp,
            @RequestParam String oid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        List<JSONObject> data=iSignInCourseService.selectapplyhistory(oid,pageSize,pageNum);
        try{
            JSONObject data1 = PageUtil.wrap(data,"data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data1.toString());
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }
    @ApiOperation("根据ccid查找cname")
    @RequestMapping(value = "/selectcnamebyccid",method = RequestMethod.GET)
    public ResponseModel selectcnamebyccid(@RequestParam String ccid) {
        if (iSignInCourseService.selectbyccid(ccid).getName() != null)
            return new ResponseModel(200, "查找成功",iSignInCourseService.selectbyccid(ccid).getName());
        else
            return new ResponseModel(500, "查找失败");
    }
    @ApiOperation("查看绑定的下级课程")
    @RequestMapping(value = "/applybindcou",method = RequestMethod.GET)
    public void selectbindcou(
            HttpServletResponse resp,
            @RequestParam String oid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        List<JSONObject> data=iSignInCourseService.selectbind(oid,pageSize,pageNum);
        try{
            JSONObject data1 = PageUtil.wrap(data,"data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data1.toString());
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }

    @ApiOperation("查看当前组织及其所有下级组织绑定的课程")
    @RequestMapping(value = "/bindallcou", method = RequestMethod.GET)
    public void selectbindallsubcou(
            HttpServletResponse resp,
            @RequestParam String oid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        List<JSONObject> data = iSignInCourseService.selectbindallsubs(oid, pageSize, pageNum);
        try {
            JSONObject wrapped = PageUtil.wrap(data, "data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            PrintWriter writer = resp.getWriter();
            writer.append(wrapped.toString());
        } catch (Exception e) {
            log.log(Level.SEVERE, "Error generating course list", e);
        }
    }


    @ApiOperation("查看绑定的下级课程根据课程名")
    @RequestMapping(value = "/applybindcoubyname",method = RequestMethod.GET)
    public void selectbindcoubyname(
            HttpServletResponse resp,
            @RequestParam String oid,
            @RequestParam String name,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        List<JSONObject> data=iSignInCourseService.selectbindbycname(oid, name, pageSize, pageNum);
        try{
            JSONObject data1 = PageUtil.wrap(data,"data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data1.toString());
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }
    @ApiOperation("查看绑定的上级组织")
    @RequestMapping(value = "/applybindsup", method = RequestMethod.GET)
    public void selectbindsup(
            HttpServletResponse resp,
            @RequestParam String ccid,
            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        List<JSONObject> data = iSignInCourseService.selectsup(ccid, pageSize, pageNum);
        try {
            JSONObject data1 = PageUtil.wrap(data, "data", pageSize, pageNum);
            resp.setCharacterEncoding("utf-8");
            /*得到输出流*/
            PrintWriter respWriter = resp.getWriter();
            /*将JSON格式的对象toString()后发送*/
            respWriter.append(data1.toString());
        } catch (Exception e) {
            log.log(Level.SEVERE, "Error parsing date", e);
        }
    }
    @ApiOperation("统计某个课程的签到")
    @RequestMapping(value = "/statisticcourse", method = RequestMethod.GET)
    public ResponseModel statisticcourse(@ApiParam(value = "签到环节ID",required = true)@RequestParam("ccid") String ccid,
                                         @RequestParam(value = "actid", required = false,defaultValue = "") String actid) {
        ResponseModel responseModel;
        try {
            List<String> lidlist=new ArrayList<>();
            if (!actid.isEmpty() && !actid.equals("")) {
                lidlist=iSignInCourseService.selectlidbyactid(actid);
            } else {
                lidlist = iSignInCourseService.selectlidbyccid(ccid);
            }
            int sum=0;
            int count = 0;
            int qiandao=0;
            int qingjia=0;
            int chidao=0;
            int qita=0;
            int weirenzheng=0;
            int kuangke=0;
            for(String lid:lidlist){
                SigninclassEntity signinclassEntity = signInClassService.selectClassbylid(lid);
                if (signinclassEntity != null) {
                    sum+=signinclassEntity.getNumber();
                }
                count += iSignInRecordService.selectRecCount(lid);
                qiandao +=iSignInRecordService.selectRecCount1(lid,1);
                qingjia +=iSignInRecordService.selectRecCount1(lid,2);
                chidao +=iSignInRecordService.selectRecCount1(lid,3);
                qita +=iSignInRecordService.selectRecCount1(lid,4);
                weirenzheng +=iSignInRecordService.selectRecCount1(lid,5);
                kuangke +=iSignInRecordService.selectRecCount1(lid,6);

            }
            ArrayList<Object> data = new ArrayList<>();
            Map<String, Object> map = new HashMap<>(1);
            map.put("总人数", sum);
            map.put("已签到", count);
            map.put("签到", qiandao);
            map.put("请假", qingjia);
            map.put("迟到", chidao);
            map.put("其他", qita);
            map.put("未认证", weirenzheng);
            map.put("旷课", kuangke);
            data.add(0, map);
            System.out.print("dhaiujwiajd"+qingjia);
            responseModel = new ResponseModel(200, "获取成功", data);
        } catch (Exception e) {
            responseModel = new ResponseModel(199, "无正在进行的考勤");
        }
        return responseModel;
    }

    @ApiOperation("获取该课程所有签到活动数据")
    @RequestMapping(value = "/getCourseAttendanceStats", method = RequestMethod.GET)
    public ResponseModel statisticcourse(@ApiParam(value = "签到环节ID",required = true)@RequestParam("ccid") String ccid) {
        try {
            // 1. 获取该课程下所有签到活动
            List<SignInActivity> activities = signInActivityService.findByCCID(ccid);

            List<Map<String, Object>> result = new ArrayList<>();

            for (SignInActivity activity : activities) {
                // 2. 对每个活动执行统计逻辑
                Map<String, Object> activityData = calculateAttendance(activity.getActId(), activity.getTitle());
                result.add(activityData);
            }

            // 3. 构建最终响应结构
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("activities", result);

            return new ResponseModel(200, "获取成功", responseData);

        } catch (Exception e) {
            return new ResponseModel(199, "系统繁忙，请稍后重试");
        }
    }

    // 复用统计逻辑的方法
    private Map<String, Object> calculateAttendance(String actid, String activityName) {
        List<String> lidList = iSignInCourseService.selectlidbyactid(actid);
        Set<String> uniqueLids = new HashSet<>(lidList); // 去重

        int totalStudents = 0;
        int qiandao = 0, qingjia = 0, chidao = 0, qita = 0, kuangke = 0;

        for (String lid : uniqueLids) {
            SigninclassEntity signinclassEntity = signInClassService.selectClassbylid(lid);
            if (signinclassEntity != null) {
                totalStudents += signinclassEntity.getNumber();
            }

            // 统计所有状态
            qiandao += iSignInRecordService.selectRecCount1(lid, 1);
            qingjia += iSignInRecordService.selectRecCount1(lid, 2);
            chidao += iSignInRecordService.selectRecCount1(lid, 3);
            qita += iSignInRecordService.selectRecCount1(lid, 4);
            kuangke += iSignInRecordService.selectRecCount1(lid, 6); // 旷课
        }

        // 计算实际出勤人数（排除旷课）
        int signedTotal = qiandao + qingjia + chidao + qita;
        kuangke = totalStudents - signedTotal; // 旷课 = 总人数 - 已统计人数

        // 构建统计对象
        Map<String, Object> stats = new LinkedHashMap<>();
        stats.put("normal", qiandao);
        stats.put("leave", qingjia);
        stats.put("late", chidao);
        stats.put("absent", kuangke);
        stats.put("other", qita);

        // 返回数据
        Map<String, Object> activityData = new LinkedHashMap<>();
        activityData.put("name", activityName);
        activityData.put("attendanceRate", totalStudents > 0 ?
                (signedTotal * 100.0 / totalStudents) : 0.0);
        activityData.put("stats", stats);

        return activityData;
    }

}
